﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Sgr.BackGroundTasks;

namespace Sgr.Sms.BackGroundTasks
{
    public class SmsSenderBackGroundTask : IBackGroundTask<SmsSenderData>
    {
        private readonly IBackGroundTaskManager _backGroundTaskManager;
        private readonly ISmsService _smsService;
        private readonly SmsOptions _options;
        private readonly ILogger<SmsSenderBackGroundTask> _logger;

        public SmsSenderBackGroundTask(
            IBackGroundTaskManager backGroundTaskManager,
            ISmsService smsService,
            IOptions<SmsOptions> options,
            ILogger<SmsSenderBackGroundTask> logger)
        {
            _backGroundTaskManager = backGroundTaskManager ?? throw new ArgumentNullException(nameof(backGroundTaskManager));
            _smsService = smsService ?? throw new ArgumentNullException(nameof(smsService));
            _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        public async Task ExecuteAsync(SmsSenderData data, CancellationToken cancellationToken = default)
        {
            ValidateData(data);

            _logger.LogInformation(
                "开始后台任务，发送短信: PhoneNumber={PhoneNumber}, RetryCount={RetryCount}/{MaxRetryCount}, TaskId={TaskId}",
                data.PhoneNumber,
                data.RetryCount,
                data.MaxRetryCount ?? _options.MaxRetryCount,
                data.TaskId);

            try
            {
                var result = await _smsService.SendAsync(
                    data.PhoneNumber,
                    data.Message,
                    cancellationToken);

                if (result.Succeeded)
                {
                    _logger.LogInformation(
                        "短信发送成功: PhoneNumber={PhoneNumber}, TaskId={TaskId}",
                        data.PhoneNumber,
                        data.TaskId);
                    return;
                }

                _logger.LogWarning(
                    "短信发送失败: PhoneNumber={PhoneNumber}, Error={Error}, TaskId={TaskId}",
                    data.PhoneNumber,
                    result.Error,
                    data.TaskId);

                await HandleFailureAsync(data, result.Error ?? "未知错误", cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,
                    "短信发送异常: PhoneNumber={PhoneNumber}, TaskId={TaskId}",
                    data.PhoneNumber,
                    data.TaskId);

                await HandleFailureAsync(data, ex.Message, cancellationToken);
            }
        }

        private static void ValidateData(SmsSenderData data)
        {
            Check.NotNull(data, nameof(data));

            if (string.IsNullOrWhiteSpace(data.PhoneNumber))
                throw new ArgumentException("手机号不能为空", nameof(data));
            if (string.IsNullOrWhiteSpace(data.Message))
                throw new ArgumentException("短信内容不能为空", nameof(data));
            if (data.MaxRetryCount.HasValue && data.MaxRetryCount.Value < 0)
                throw new ArgumentException("最大重试次数不能小于0", nameof(data));
        }

        private async Task HandleFailureAsync(SmsSenderData data, string error, CancellationToken cancellationToken = default)
        {
            int max = data.MaxRetryCount ?? _options.MaxRetryCount;
            if (data.RetryCount >= max)
            {
                _logger.LogError(
                    "短信发送失败且达到最大重试次数: PhoneNumber={PhoneNumber}, Error={Error}, TaskId={TaskId}",
                    data.PhoneNumber,
                    error,
                    data.TaskId);
                return;
            }

            await CreateRetryTask(data, cancellationToken);
        }

        private async Task CreateRetryTask(SmsSenderData data, CancellationToken cancellationToken = default)
        {
            var retryData = new SmsSenderData
            {
                TaskId = data.TaskId,
                PhoneNumber = data.PhoneNumber,
                Message = data.Message,
                RetryCount = data.RetryCount + 1,
                MaxRetryCount = data.MaxRetryCount ?? _options.MaxRetryCount
            };

            await _backGroundTaskManager.EnqueueAsync<SmsSenderBackGroundTask, SmsSenderData>(
                retryData,
                delay: TimeSpan.FromSeconds(_options.RetryIntervalSeconds),
                cancellationToken);

            _logger.LogInformation(
                "已创建重试任务: PhoneNumber={PhoneNumber}, NextRetryCount={RetryCount}, TaskId={TaskId}",
                data.PhoneNumber,
                retryData.RetryCount,
                data.TaskId);
        }
    }
}